package com.xiang.ad.index.district;

import com.xiang.ad.index.IndexAware;
import com.xiang.ad.search.vo.feature.DistrictFeature;
import com.xiang.ad.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.stream.Collectors;

/**
 * Created by xiang.
 * 地域index服务
 * 推广单元的限制维度  使用倒排索引，以地域的形式寻找推广单元的id，一个地域可以对应到多个推广单元的id
 */
@Slf4j
@Component
public class UnitDistrictIndex implements IndexAware<String, Set<Long>> {//key是省-市，value是unitId

    private static Map<String, Set<Long>> districtUnitMap;//倒排索引-通过 地域限制 查询 unitId
    private static Map<Long, Set<String>> unitDistrictMap;//正向索引-通过 unitId 查询 地域限制

    //使用ConcurrentHashMap初始化map
    static {
        districtUnitMap = new ConcurrentHashMap<>();
        unitDistrictMap = new ConcurrentHashMap<>();
    }

    //通过（省-市）get UnitId
    @Override
    public Set<Long> get(String key) {
        return districtUnitMap.get(key);
    }

    //添加索引
    @Override
    public void add(String key, Set<Long> value) {

        log.info("UnitDistrictIndex, before add: {}", unitDistrictMap);

        //key：地域   value：unitIds
        Set<Long> unitIds = CommonUtils.getorCreate(
                key,
                districtUnitMap,
                ConcurrentSkipListSet::new
        );
        unitIds.addAll(value);

        //key：unitIds   value：地域
        for (Long unitId : value) {

            Set<String> districts = CommonUtils.getorCreate(
                    unitId,
                    unitDistrictMap,
                    ConcurrentSkipListSet::new
            );
            districts.add(key);
        }

        log.info("UnitDistrictIndex, after add: {}", unitDistrictMap);
    }

    //更新索引，不提供更新方法，set的更新成本太高
    // 更新，会导致两个map发生改变，而且每一个map都会牵扯到一个set，需要对set遍历，所以更新成本非常高
    @Override
    public void update(String key, Set<Long> value) {

        log.error("district index can not support update");
    }

    //删除索引
    @Override
    public void delete(String key, Set<Long> value) {

        log.info("UnitDistrictIndex, before delete: {}", unitDistrictMap);
        //districtUnitMap
        Set<Long> unitIds = CommonUtils.getorCreate(
                key,
                districtUnitMap,
                ConcurrentSkipListSet::new
        );
        unitIds.removeAll(value);

        //unitDistrictMap
        for (Long unitId : value) {

            Set<String> districts = CommonUtils.getorCreate(
                    unitId,
                    unitDistrictMap,
                    ConcurrentSkipListSet::new
            );
            districts.remove(key);
        }

        log.info("UnitDistrictIndex, after delete: {}", unitDistrictMap);
    }

    // 匹配
    // 根据地域feature对推广单元进行再筛选
    public boolean match(Long adUnitId,
                         List<DistrictFeature.ProvinceAndCity> districts) {

        //非空判断
        if (unitDistrictMap.containsKey(adUnitId) &&
                CollectionUtils.isNotEmpty(unitDistrictMap.get(adUnitId))) {

            Set<String> unitDistricts = unitDistrictMap.get(adUnitId);

            List<String> targetDistricts = districts.stream()
                    .map(
                            d -> CommonUtils.stringConcat(
                                    d.getProvince(), d.getCity()
                            )
                    ).collect(Collectors.toList());

            return CollectionUtils.isSubCollection(targetDistricts, unitDistricts);
        }

        return false;
    }
}
